use core::{ffi::c_char, ptr::null_mut};

use crate::{
    c::{
        osMutexAcquire, osMutexAttr_t, osMutexId_t, osMutexNew, osMutexPrioInherit,
        osMutexRecursive, osMutexRelease, osMutexRobust, osRtxMutex_t,
    },
    osWaitForever,
    utils::Store,
};

const CB_SIZE: usize = size_of::<osRtxMutex_t>();

pub struct Mutex {
    cb_mem: Store<CB_SIZE>,
    id: osMutexId_t,
}

impl Mutex {
    pub const fn const_new() -> Self {
        Self {
            cb_mem: Store::const_new(),
            id: null_mut(),
        }
    }

    pub fn create(&mut self, name: &str) {
        let attr = osMutexAttr_t {
            name: name.as_ptr() as *const c_char,
            attr_bits: osMutexRobust | osMutexPrioInherit | osMutexRecursive,
            cb_mem: self.cb_mem.c_ptr(),
            cb_size: CB_SIZE as u32,
        };
        self.id = unsafe { osMutexNew(&attr) };
        debug_assert!(self.id != null_mut(), "mutex create fail");
    }

    pub fn lock(&self) {
        unsafe {
            osMutexAcquire(self.id, osWaitForever);
        }
    }

    pub fn unlock(&self) {
        unsafe {
            osMutexRelease(self.id);
        }
    }
}
